#include "Clouds.h"



/*
TODO
ok, i need to find a way to iterate through this little cloud object's scene graph and destroy 
orphaned spheres and find a way to connect spheres that are fairly close together.
ASK CAMERON AND CHRIS WALKER.
*/
Clouds::Clouds(int cloudCov, float cloudShar, int r, int c)
{
	rows = r;
	cols = c;

	cloudCover = cloudCov;
	cloudSharpness = cloudShar;
	//heightMap = new int [256][256];
	//exponHeightMap = new int [256][256];
	//heightMap = int*(malloc(256*256));
	//exponHeightMap = malloc(256*256);
	heightMap.resize(rows);
	for(int i=0;i<rows;i++)
		heightMap[i].resize(cols);
	exponHeightMap.resize(rows);
	for(int i=0;i<rows;i++)
		exponHeightMap[i].resize(cols);

	genBasicHeightMap();
}
Clouds::Clouds() {}

Clouds::~Clouds() {}

void Clouds::genBasicHeightMap()
{
	PerlinNoise perl;
	perl = PerlinNoise(1.0,2.0,8);
	for (int i=0;i<rows;i++)
	{
		for (int j=0;j<cols;j++)
		{
			heightMap[i][j] = perl.perlNoise2D(i,j,true);
		}
	}
	for (int i=0;i<rows;i++)
	{
		for (int j=0;j<cols;j++)
		{
			exponHeightMap[i][j] = exponFun(heightMap[i][j]);
		}
	}
	specialAlgorithm();

}

int Clouds::getHeightMap(int x, int y)
{
	return heightMap[x][y];
}
int Clouds::getExponHeightMap(int x, int y)
{
	return exponHeightMap[x][y];
}

int Clouds::exponFun(int v)
{
	int c = v-cloudCover;	
	
	if(c<0)
		c=0;

	int cloudDensity = 255 - (pow(cloudSharpness, c) * 255);
	return cloudDensity;
}

void Clouds::specialAlgorithm()
{
	for(int i=0;i<rows;i++)
	{
		for(int j=0;j<cols;j++)
		{
			nearby=false;
			origX = i;
			origY = j;

			if (exponHeightMap[i][j]>75)
			{
				//if((i<59 && i>4) && (j>4 && j<59))
				//{
					anotherHelperFunction(i,j,true,5);
					nearby=false;
					specialAlgHelper(i,j,true,3);
				//}
					//if((x>4 || y>4) || (x<250||y<250))
			}
		}
	}
}

void Clouds::specialAlgHelper(int x, int y,bool first,int depth)
{
	if(depth==0)
		return;
	/*std::cout << x;
	std::cout << " ";
	std::cout << y;
	std::cout << " ";
	std::cout << depth;
	std::cout << "\n";*/

	if(first==false)
	{//127
		if (exponHeightMap[x][y]>127);
			nearby=true;	
	}
		if((x-1)>0)
			specialAlgHelper(x-1,y,false,depth-1);

		if((y-1)>0)
			specialAlgHelper(x,y-1,false,depth-1);

		//specialAlgHelper(x-1,y-1,false,depth-1);
		/*if ((x+1)<rows)
		{
			if(specialAlgHelper(x+1,y,false,depth-1)==true)
			{
				exponHeightMap[x][y]=255;
				return true;
			}
		}*/
		if ((x+1)<rows)
			specialAlgHelper(x+1,y,false,depth-1);

		if ((y+1)<rows)
			specialAlgHelper(x,y+1,false,depth-1);
		//specialAlgHelper(x+1,y+1,false,depth-1);
	if(first==true)
	{
		if (nearby==false)
		{
			//std::cout << "TRUF";
			//std::cout << "\n";
			exponHeightMap[x][y]=0;
		}
	}
}

void Clouds::anotherHelperFunction(int x, int y, bool first, int depth)
{
	if(depth==0)
		return;

	if(first==false)
	{
		int comp = exponHeightMap[x][y];
		if (comp>200)
		{
			std::cout << exponHeightMap[x][y];
			std::cout << " "; 
			std::cout << comp;
			std::cout << "\n";


			nearby=true;
			drawExtras(x,y);
			std::cout << "Truth reached.";
			std::cout << "\n";
		}
	}
		if((x-1)>0)
		{
			anotherHelperFunction(x-1,y,false,depth-1);
		}
		if((y-1)>0)
		{
			anotherHelperFunction(x,y-1,false,depth-1);
		}
		//specialAlgHelper(x-1,y-1,false,depth-1);
		if ((x+1)<rows)
		{
			anotherHelperFunction(x+1,y,false,depth-1);
		}
		if ((y+1)<rows)
		{
			anotherHelperFunction(x,y+1,false,depth-1);
		}
		//specialAlgHelper(x+1,y+1,false,depth-1);


}

void Clouds::drawExtras(int x, int y)
{
	/*std::cout << origX;
	std::cout << " ";
	std::cout << x;
	std::cout << " ";
	std::cout << origY;
	std::cout << " ";
	std::cout << y;
	std::cout << "\n";*/

	PerlinNoise perl;
	perl = PerlinNoise(0.7,2.0,8);


	if( (origX-x)<0 && (origY-y)<0)
	{
		for(int i=origX;i<=x;i++)
		{
			for(int j=origY;j<=y;j++)
			{
				if(perl.perlNoise2D(i,j,false)>0)
					exponHeightMap[i][j]=254;
			}
		}
	}
	if( (origX-x)<0 && (origY-y)>0)
	{
		for(int i=origX;i<=x;i++)
		{
			for(int j=origY;j>=y;j--)
			{
				if(perl.perlNoise2D(i,j,false)>0)
					exponHeightMap[i][j]=254;
			}
		}
	}
	if( (origX-x)>0 && (origY-y)<0)
	{
		for(int i=origX;i>=x;i--)
		{
			for(int j=origY;j<=y;j++)
			{
				if(perl.perlNoise2D(i,j,false)>0)
					exponHeightMap[i][j]=254;
			}
		}
	}
	if( (origX-x)>0 && (origY-y)>0)
	{
		for(int i=origX;i>=x;i--)
		{
			for(int j=origY;j>=y;j--)
			{
				if(perl.perlNoise2D(i,j,false)>0)
					exponHeightMap[i][j]=254;
			}//0.05
		}
	}
}





/*void setval(int x,int y,int v)
{
	*(heightMap+(256*y)+x)
}
int getVal(int x, int y)
{
	*(heightMap+(256*y)+x) = v;
}*/

/*int main(void)
{
	Clouds cld;
	cld = Clouds(215,0.5,256,256);
	for (int i=0; i<256; i++)
	{
		for(int j=0; j<256; j++)
		{
			std::cout << i;
			std::cout << " ";
			std::cout << j;
			std::cout << " ";
			std::cout << cld.getHeightMap(i,j);
			std::cout << "\n";
		}
	}

	std::cout << "\n";
	std::cout << "\n";
	std::cout << "\n";
	
	for (int i=0; i<256; i++)
	{
		for(int j=0; j<256; j++)
		{
			std::cout << i;
			std::cout << " ";
			std::cout << j;
			std::cout << " ";
			std::cout << cld.getExponHeightMap(i,j);
			std::cout << "\n";
		}
	}

}*/